﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RayTracing
{
    public class P3
    {
        public float x, y, z;                           // x, y, and z cordnates for a point in 3-space.
                                                        // x = left,right.
                                                        // y = forward, back.
                                                        // z = up, down.
                                                        // why? Because.

        public P3(float x, float y, float z)            // Basic constructor takes the float x,y, and z.
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public P3(P3 p)                                 // creates a new p3 from an old one.
        {
            this.x = p.x;
            this.y = p.y;
            this.z = p.z;
        }

        public static P3 add(P3 p, P3 p2)               // static method to add two P3's component wise.
        {
            return new P3(p.x + p2.x, p.y + p2.y, p.z + p2.z);
        }

        public P3 add(P3 p)                             // adds two P3's calls static method add.
        {
            return P3.add(this, p);
        }

        public static P3 sub(P3 p, P3 p2)               // static method to subtract two P3's component wise.
        {
            return new P3(p.x - p2.x, p.y - p2.y, p.z - p2.z);
        }

        public P3 sub(P3 p)                             // subtracts two P3's calls static method sub.
        {
            return P3.sub(this, p);
        }

        public static P3 mul(P3 p, P3 p2)              // static method to multiply two P3's component wise.
        {
            return new P3(p.x*p2.x, p.y*p2.y, p.z*p2.z);
        }

        public P3 mul(P3 p)                            // multiplies two P3's calls static method mul.
        {
            return P3.mul(this, p);
        }

        public static P3 scale(P3 p, float scaler)     // static method to scale a P3 by a value.
        {
            return new P3(p.x * scaler, p.y * scaler, p.z * scaler);
        }

        public P3 scale(float s)                        // scales a P3 calls static method scale.
        {
            return P3.scale(this, s);
        }

        public static float norm(P3 p)                  // norms a point (Dark Magic).
        {
            return ((float) Math.Sqrt((p.x * p.x + p.y * p.y + p.z * p.z)));
        }

        public static P3 normalize(P3 p)                // nomalizes a point(Deep Magic).
        {
            if (norm(p) == 0)
            {
                return new P3(0, 0, 0);
            }
            else
            {
                return scale(p, (float)(1.0 / (norm(p) * 1.0)));
            }
        }

        public static float dot(P3 p, P3 p2)            // dot product of two points.(Deep Dark Magic).
        {
            return ((p.x * p2.x) + (p.y * p2.y) + (p.z * p2.z));
        }

        public static P3 cross(P3 p,P3 p2){             // cross product of two points. (Extremely Deep Dark Magic). 
            float x = (p.y * p2.z) - (p.z * p2.y);
            float y = (p.z * p2.x) - (p.x * p2.z);
            float z = (p.x * p2.y) - (p.y * p2.x);
        return new P3(x,y,z);
    }

        public static P3 fromSpherical(float heading, float pitch)      // because we need it. what it does no one knows... yet.
        {
            float x = (float) (Math.Sin(heading) * Math.Cos(pitch));
            float y = (float) (Math.Sin(heading) * Math.Sin(pitch));
            float z = (float) Math.Cos(heading);
            return new P3(x, y, z);
        }

    }
}


